#include "test_byte.h"
#include "string.h"
#include "stdlib.h"

#include "esp_timer.h"
#include "esp_log.h"
#include "esp_sleep.h"

#include "driver/gpio.h"

static int lua_init_byte(lua_State *L){
    char*buf=(char*)lua_newuserdata(L,200);
    if(buf!=NULL){
        memset(buf,0,200);
        buf[0]='z';
        buf[1]='h';
        buf[2]='a';
        buf[3]='n';
        buf[4]='g';
        printf("point:%s\r\n",buf);
        return 1;
    }
    return 0;
}

static int lua_print(lua_State *L){
    printf("hello test byte\r\n");
    char*buf=(char*)lua_touserdata(L,1);
    if(buf!=NULL){
        printf("point2:%s\r\n",buf);
    }else{
        printf("NULL\r\n");
    }
    return 0;
}


//回调函数测试，有其他参数放在最前面
static int lua_callback =0;
static int lua_byte_call(lua_State *L){
    
    /*
    // 方式1
    int time=luaL_checkinteger(L,1);
    printf("time:%d\r\n",time);
    luaL_checktype(L, 2, LUA_TFUNCTION);
    lua_pushnumber(L, 3);
    lua_pushnumber(L, 2);
    lua_pushstring(L, "zhang");
    lua_call(L, 3, 1);
    //lua_call的第二个参数：传入f中一个参数，lua_call的第三个参数：f的返回值是一个参数
    */
    //方式2结合 lua_byte_run函数模拟回调
    int time=luaL_checkinteger(L,1);
    printf("time:%d\r\n",time);
    lua_callback = luaL_ref(L, LUA_REGISTRYINDEX);
    printf("index:%d\r\n",lua_callback);
    
    return 0;
}

static int lua_byte_run(lua_State *L){
    printf("--------lua_byte_run,%d\r\n",lua_callback);
    lua_rawgeti(L, LUA_REGISTRYINDEX, lua_callback);

    lua_pushnumber(L, 3);
    lua_pushnumber(L, 2);
    lua_pushstring(L, "zhang");
    lua_call(L, 3, 1);
    return 0;
}


typedef struct {
    lua_State *L;
    const char*name;
    int funcIndex;
    int time;
}lua_user_timer;

static void periodic_timer_callback(void* arg){
   lua_user_timer* tm=(lua_user_timer*)arg;
   lua_State *L=tm->L;
    lua_rawgeti(L, LUA_REGISTRYINDEX, tm->funcIndex);
    lua_pushstring(L, tm->name);
    lua_pushinteger(L,tm->time);
    lua_call(L, 2, 0);

}



static int lua_timer(lua_State *L){
    lua_user_timer*tm=(lua_user_timer*)malloc(sizeof(lua_user_timer));
    const char*name=luaL_checkstring(L,1);
    tm->L=L;
    int ttm=luaL_checkinteger(L,2);
    tm->time=ttm;
    tm->name=name;
    int funcIndex = luaL_ref(L, LUA_REGISTRYINDEX);
    tm->funcIndex=funcIndex;
    const esp_timer_create_args_t periodic_timer_args = {
            .callback = &periodic_timer_callback,
            /* name is optional, but may help identify the timer when debugging */
            .arg = (void*) tm,
            .name = name,
    };
    esp_timer_handle_t periodic_timer;
    ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
    ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, ttm));
    return 0;
}





static const luaL_Reg arrayFunc[] ={
    {"initByte", lua_init_byte},
	{"bytePrint", lua_print},
    {"byteCall", lua_byte_call},
    {"byteRun", lua_byte_run},
    {"timer",lua_timer},//定时任务测试
	{NULL, NULL}
};



//下面两个直接注册成模块
LUAMOD_API int luaopen_testfunc (lua_State *L) {
  luaL_newlib(L, arrayFunc);
  return 1;
}

LUAMOD_API int luaopen_testbyte(lua_State *L){
    //直接将函数注册到全局
    lua_pushglobaltable(L);
    luaL_setfuncs(L, arrayFunc, 0);
    /* set global _G */
    lua_pushvalue(L, -1);
    lua_setfield(L, -2, LUA_GNAME);
    /* set global _VERSION */
    lua_pushliteral(L, LUA_VERSION);
    lua_setfield(L, -2, "_VERSION");
    return 1;
}


extern int luaopen_student_libs (lua_State *L) ;
extern int luaopen_user_timer_libs (lua_State *L) ;
extern int luaopen_memlibs(lua_State *L) ;


LUALIB_API void luaopen_testlib(lua_State *L){
    luaL_requiref(L, "test2", luaopen_testfunc, 1);
    lua_pop(L, 1);  /* remove lib */

    luaL_requiref(L, "Student", luaopen_student_libs, 1);
    lua_pop(L, 1);  /* remove lib */

    luaL_requiref(L, "Timer", luaopen_user_timer_libs, 1);
    lua_pop(L, 1);  /* remove lib */

    luaL_requiref(L, "Mem", luaopen_memlibs, 1);
    lua_pop(L, 1);  /* remove lib */
}